package coll

import (
	"gitee.com/hongzhaomin/hzm-common-go/assert"
	"gitee.com/hongzhaomin/hzm-common-go/streams"
)

type Map[K comparable, V any] map[K]V

func NewMap[K comparable, V any]() *Map[K, V] {
	return NewMapWithCap[K, V](0)
}

func NewMapWithCap[K comparable, V any](cap int) *Map[K, V] {
	m := make(map[K]V, cap)
	return (*Map[K, V])(&m)
}

func OfMap[K comparable, V any](m map[K]V) *Map[K, V] {
	newMap := NewMapWithCap[K, V](len(m))
	for k, v := range m {
		newMap.Put(k, v)
	}
	return newMap
}

func (my *Map[K, V]) Put(key K, val V) {
	(*my)[key] = val
}

func (my *Map[K, V]) Get(key K) (V, bool) {
	v, ok := (*my)[key]
	return v, ok
}

func (my *Map[K, V]) Keys() []K {
	keys := make([]K, 0, len(*my))
	for k := range *my {
		keys = append(keys, k)
	}
	return keys
}

func (my *Map[K, V]) Values() []V {
	values := make([]V, 0, len(*my))
	for _, value := range *my {
		values = append(values, value)
	}
	return values
}

func (my *Map[K, V]) Entries() []MapNode[K, V] {
	nodes := make([]MapNode[K, V], 0, len(*my))
	for key, value := range *my {
		nodes = append(nodes, MapNode[K, V]{Key: key, Value: value})
	}
	return nodes
}

func (my *Map[K, V]) Stream() streams.Stream[MapNode[K, V]] {
	return streams.OfSlice(my.Entries())
}

func (my *Map[K, V]) ForEach(action func(key K, val V)) {
	assert.NonNil(action, "action func must not nil")
	for key, value := range *my {
		action(key, value)
	}
}

func (my *Map[K, V]) ContainsKey(key K) bool {
	_, ok := (*my)[key]
	return ok
}

func (my *Map[K, V]) Remove(key K) {
	delete(*my, key)
}

func (my *Map[K, V]) Size() int {
	return len(*my)
}

func (my *Map[K, V]) IsEmpty() bool {
	return (*my) == nil || len(*my) <= 0
}

type MapNode[K comparable, V any] struct {
	Key   K
	Value V
}
